/******************************************************************************
* File Name:   main.c
*
* Description: This is the source code for the XMC MCU: UART Shell Example
*              for ModusToolbox.
*
* Related Document: See README.md
*
******************************************************************************
*
* Copyright (c) 2015-2024, Infineon Technologies AG
* All rights reserved.
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/

#include <stdio.h>

#include "cybsp.h"
#include "cy_utils.h"

#include "cy_retarget_io.h"
#include "shell.h"
#include "ring_buffer.h"

#define SERIAL_BUFFER_SIZE 128
/* Defines priority level of the DEBUG_UART receive event interrupt */
#define DEBUG_UART_RECEIVE_EVENT_PRIORITY 63

/*******************************************************************************
* Forward declarations of function names
*******************************************************************************/

void help_cmd(int32_t argc, char **argv);
void led_cmd(int32_t argc, char **argv);

/*******************************************************************************
* Variables
*******************************************************************************/
/* Declaration of shell commands */
const shell_command_t cmd_table[] =
{
    {"help", 0u, 0u, help_cmd, "Display this help message", ""},
    {"ledport", 1u, 1u, led_cmd, "Led port output control", "<high|low>"},
    {0, 0u, 0u, 0, 0, 0}
};

/* Create a buffer with specified size to implement a ring buffer for data received/sent by UART */
RING_BUFFER_DEF(serial_buffer, SERIAL_BUFFER_SIZE);

/*******************************************************************************
* Function Name: CYBSP_DEBUG_UART_RECEIVE_EVENT_HANDLER
********************************************************************************
* Summary:
* Interrupt triggered for every received character on UART
*
* Parameters:
*  void
*
* Return:
*  void
*
*******************************************************************************/
void CYBSP_DEBUG_UART_RECEIVE_EVENT_HANDLER(void)
{
    static uint8_t data;

    /* Receive single characters from UART and push into ringbuffer */
    data = XMC_UART_CH_GetReceivedData(CYBSP_DEBUG_UART_HW);
    ring_buffer_put(&serial_buffer, data);
}

/*******************************************************************************
* Function Name: help_cmd
********************************************************************************
* Summary:
* Implementation of shell help command
*
* Parameters:
*  int32_t argc: argument count
*  char **argv:  pointer to argument array
*
* Return:
*  void
*
*******************************************************************************/
void help_cmd(int32_t argc, char **argv)
{
    (void)argc;
    (void)argv;

    shell_help();
}

/*******************************************************************************
* Function Name: led_cmd
********************************************************************************
* Summary:
* Implementation of shell led command
* Used to control the output state of the GPIO pin that drives an LED.
*
* Parameters:
*  int32_t argc: argument count
*  char **argv:  pointer to argument array
*
* Return:
*  void
*
*******************************************************************************/
void led_cmd(int32_t argc, char **argv)
{
    if (argc == 2)
    {
        if ((strlen(argv[1]) == (strlen("low"))) && (strncmp(argv[1], "low", strlen(argv[1]) ) == 0))
        {
#if (UC_SERIES == XMC11) || (UC_SERIES == XMC12) || (UC_SERIES == XMC13)
            XMC_GPIO_SetOutputHigh(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);
#else
            XMC_GPIO_SetOutputLow(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);
#endif
        }
        else if ((strlen(argv[1]) == (strlen("high"))) && (strncmp(argv[1], "high", strlen(argv[1]) ) == 0))
        {
#if (UC_SERIES == XMC11) || (UC_SERIES == XMC12) || (UC_SERIES == XMC13)
            XMC_GPIO_SetOutputLow(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);
#else
            XMC_GPIO_SetOutputHigh(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);
#endif
        }
        else
        {
            shell_println("Argument not supported");
        }
    }
}

/*******************************************************************************
* Function Name: my_shell_init
********************************************************************************
* Summary:
* Welcome screen shown when shell is initialized
*
* Parameters:
*  void
*
* Return:
*  void
*
*******************************************************************************/
void my_shell_init(void)
{
    const char DELIMITER_STR[] = "************************************************";

    shell_println("\r\n%s", DELIMITER_STR);
    shell_println(" %s", "Shell Application");
    shell_println(DELIMITER_STR);
    shell_println(" Version %s", "1.0.0");
    shell_println(" Built %s", __DATE__ " at " __TIME__);

    shell_println("\n Enter 'help' for command list.");
    shell_println("%s\n", DELIMITER_STR);
}

/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
* This is the main function. It initializes the UART and shell interface
* and processes the shell state machine inside the main loop.
*
* Parameters:
*  void
*
* Return:
*  int
*
*******************************************************************************/
int main(void)
{
    cy_rslt_t result;

    /* Initialize the device and board peripherals */
    result = cybsp_init();
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    /* Initialize printf retarget */
    cy_retarget_io_init(CYBSP_DEBUG_UART_HW);
    serial_buffer.head = 0;
    serial_buffer.tail = 0;

    /* Enable IRQ */
    NVIC_EnableIRQ(CYBSP_DEBUG_UART_RECEIVE_EVENT_IRQN);

    /* Initialize the shell processing */
    shell_init(cmd_table, my_shell_init);

    while (1)
    {
        /* Repeatedly execute the shell state machine */
        shell_state_machine();
    }
}

/* [] END OF FILE */
